from fastapi import APIRouter, Response, Request
from fastapi.responses import HTMLResponse,StreamingResponse
import asyncio
import json
from datetime import datetime
from typing import Dict, Optional

sse_router = APIRouter()

# 全局存储：保存客户端数据（key: client_id, value: 客户端发送的数据）
client_data_store: Dict[str, Dict] = {}

# 模拟实时数据生成（根据客户端数据调整）
async def get_real_time_data(client_id: str) -> dict:
    """根据客户端数据生成实时数据"""
    # 从全局存储获取客户端数据（默认订阅"temperature"）
    client_data = client_data_store.get(client_id, {"topic": "temperature"})
    topic = client_data.get("topic", "temperature")
    
    # 根据主题生成对应数据
    if topic == "temperature":
        return {
            "timestamp": datetime.now().isoformat(),
            "topic": topic,
            "data": {"value": round(datetime.now().second * 0.5, 1), "unit": "℃"}
        }
    elif topic == "humidity":
        return {
            "timestamp": datetime.now().isoformat(),
            "topic": topic,
            "data": {"value": round(datetime.now().second * 0.8, 1), "unit": "%"}
        }
    else:
        return {
            "timestamp": datetime.now().isoformat(),
            "topic": "unknown",
            "data": {"message": "无效主题"}
        }

# SSE事件生成器（核心逻辑）
async def sse_generator(client_id: str):
    """异步生成SSE事件（根据客户端数据调整）"""
    try:
        t= 0
        while True:
            # 获取实时数据（根据客户端数据）
            data = await get_real_time_data(client_id)
            
            # 构造SSE事件
            sse_event = (
                f"event: real_time_update\n"
                f"id: event_{datetime.now().microsecond}\n"
                f"data: {json.dumps(data)}\n\n"
            )
            
            # 推送事件
            yield sse_event
            t=t+1
            if t>=3:
                return
            # 模拟数据更新延迟
            await asyncio.sleep(1)
    
    except ConnectionResetError:
        # 客户端断开连接，清理资源
        if client_id in client_data_store:
            del client_data_store[client_id]
        print(f"客户端[{client_id}]断开连接，已清理数据")
    except Exception as e:
        # 捕获错误，推送错误事件
        error_event = (
            f"event: error\n"
            f"data: {json.dumps({'error': str(e)})}\n\n"
        )
        yield error_event
        print(f"推送错误：{e}")

# SSE路由（向客户端推送实时数据）
@sse_router.get("/sse/{client_id}", response_class=StreamingResponse)
async def sse_endpoint(client_id: str, response: Response):
    """SSE接口（根据客户端ID推送对应数据）"""
    # 设置SSE响应Headers
    response.headers["Cache-Control"] = "no-cache"
    response.headers["Connection"] = "keep-alive"
    response.headers["Transfer-Encoding"] = "chunked"
    response.headers["Content-Type"] = "text/event-stream"
    
    # 返回StreamingResponse
    return StreamingResponse(
        content=sse_generator(client_id),
        media_type="text/event-stream"
    )

# 客户端数据提交接口（POST）
@sse_router.post("/client/data/{client_id}")
async def submit_client_data(client_id: str, request: Request):
    """接收客户端发送的数据（如订阅主题）"""
    try:
        # 解析客户端发送的JSON数据
        data = await request.json()
        # 保存到全局存储（覆盖旧数据）
        client_data_store[client_id] = data
        # 返回成功响应
        return {"status": "success", "message": "数据已接收", "client_id": client_id, "data": data}
    except Exception as e:
        return {"status": "error", "message": str(e)}

# 测试页面（用于验证）
@sse_router.get("/sseceshi", response_class=HTMLResponse)
async def index():
    """测试页面（包含客户端发送数据的功能）"""
    return """
    <html>
        <head>
            <title>SSE with Client Data Demo</title>
            <style>
                .container { max-width: 800px; margin: 0 auto; padding: 20px; }
                .form-group { margin-bottom: 20px; }
                .form-group label { display: block; margin-bottom: 5px; }
                .form-group input { padding: 10px; width: 200px; }
                .form-group button { padding: 10px 20px; background-color: #007bff; color: #fff; border: none; border-radius: 5px; cursor: pointer; }
                .data-container { margin-top: 20px; padding: 20px; border: 1px solid #eee; border-radius: 5px; }
                .data-container p { margin: 5px 0; }
            </style>
        </head>
        <body>
            <div class="container">
                <h1>SSE 客户端数据提交示例</h1>
                
                <!-- 客户端ID输入 -->
                <div class="form-group">
                    <label for="client-id">客户端ID（必填）</label>
                    <input type="text" id="client-id" placeholder="如：client_123" required>
                </div>
                
                <!-- 主题选择 -->
                <div class="form-group">
                    <label for="topic">订阅主题（可选）</label>
                    <input type="text" id="topic" placeholder="如：temperature/humidity" value="temperature">
                </div>
                
                <!-- 提交按钮 -->
                <div class="form-group">
                    <button onclick="submitData()">提交数据</button>
                </div>
                
                <!-- 实时数据展示 -->
                <div class="data-container">
                    <h2>实时数据（客户端ID：<span id="display-client-id"></span>）</h2>
                    <p>主题：<span id="topic-display"></span></p>
                    <p>时间：<span id="timestamp-display"></span></p>
                    <p>数据：<span id="data-display"></span></p>
                </div>
            </div>
            
            <script>
                let eventSource;
                let clientId;
                
                // 提交数据到服务器
                function submitData() {
                    clientId = document.getElementById('client-id').value.trim();
                    const topic = document.getElementById('topic').value.trim();
                    
                    if (!clientId) {
                        alert('客户端ID不能为空');
                        return;
                    }
                    
                    // 发送POST请求到服务器
                    fetch(`/client/data/${clientId}`, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify({ topic: topic })
                    })
                    .then(response => response.json())
                    .then(data => {
                        if (data.status === 'success') {
                            alert('数据提交成功');
                            // 启动或重启SSE连接
                            startSSE(clientId);
                        } else {
                            alert('数据提交失败：' + data.message);
                        }
                    })
                    .catch(error => {
                        alert('数据提交失败：' + error.message);
                    });
                }
                
                // 启动SSE连接
                function startSSE(clientId) {
                    // 关闭现有连接（如果有的话）
                    if (eventSource) {
                        eventSource.close();
                    }
                    
                    // 初始化EventSource
                    eventSource = new EventSource(`/sse/${clientId}`);
                    
                    // 监听实时更新事件
                    eventSource.addEventListener('real_time_update', (event) => {
                        const data = JSON.parse(event.data);
                        // 更新页面展示
                        document.getElementById('display-client-id').textContent = clientId;
                        document.getElementById('topic-display').textContent = data.topic;
                        document.getElementById('timestamp-display').textContent = data.timestamp;
                        document.getElementById('data-display').textContent = JSON.stringify(data.data);
                    });
                    
                    // 监听错误事件
                    eventSource.addEventListener('error', (event) => {
                        console.error('SSE错误：', event);
                        eventSource.close();
                    });
                }
            </script>
        </body>
    </html>
    """